package pearson.automation.forms.courseDetails.module;

import java.util.ArrayList;
import java.util.List;

import junit.framework.Assert;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.RemoteWebElement;

import framework.BaseForm;
import framework.elements.Button;
import framework.elements.ElementList;
import framework.elements.Label;
import framework.elements.Link;
import framework.elements.TextBox;

/**
 * This form describes each module element in TOC
 * 
 * 
 */
public final class ModuleForm extends BaseForm {

    private Label module;
    private Button toggler;
    private Label handler;
    private Link moduleTitle;
    private ElementList sectionTitles;
    private ElementList sectionIDs;
    private ElementList moduleAssets;
    private Button delete;
    private Button deleteConfirm;
    private Button duplicate;
    private Label lock;
    private static final String modulexPathTemplate =
        "//li[contains(@class,'module')]/div[@title='%1$s']/..";
    private static final String moduleTogglexPathTemplate =
        "//li[@data-module-ref='%1$s']//a[contains(@class,'toggler')]";
    private static final String handlerXPathTemplate =
        "//li[@data-module-ref='%1$s']/div[contains(@class,'container-left')]";
    private static final String moduleTitlexPathTemplate =
        "//li[@data-module-ref='%1$s']//*[@class='module-title']/a";
    private static final String moduleAssetxPathTemplate =
        "//li[@data-module-ref='%1$s']//a[@class='asset-title']";
    private static final String sectionTitleList =
        "//li[@data-module-ref='%1$s']//ol[contains(@class,'section-list')]"
      + "/li/a[@class='section-title']";
    private static final String sectionIDList =
        "//li[@data-module-ref='%1$s']//ol[contains(@class,'section-list')]"
      + "/li/span[@class='section-numbering']";
    private static final String lockSign =
        "//li[@data-module-ref='%1$s']/span[@class='locked-icon']";
    private static final String deleteTemplate =
        "//li[@data-module-ref='%1$s']/div[contains(@class,'container-right')]"
      + "/div[@class='edit-links']/a[@class='delete']";
    private static final String deleteConfirmTemplate =
        "//li[@data-module-ref='%1$s']/div[contains(@class,'container-right')]"
      + "/a[text()='Delete']";
    private static final String duplicateTemplate =
        "//li[@data-module-ref='%1$s']/div[contains(@class,'container-right')]"
      + "/div[@class='edit-links']/a[@class='duplicate']";
    
    
    private static final String sectionTemplate =
        "(//li[@data-module-ref='%1$s']//ol[contains(@class,'section-list')]"
      + "/li)[%2$s]";
    private static final String sectionTitle =
        "//li[@data-section-ref='%1$s']/a[@class='section-title']/span";
    private static final String deleteSectionTemplate =
        "//li[@data-section-ref='%1$s']"
      + "/div[@class='edit-links']/a[@class='delete']";
    private static final String duplicateSectionTemplate =
        "//li[@data-section-ref='%1$s']"
      + "/div[@class='edit-links']/a[@class='duplicate']";
    private static final String deleteSectionConfirmTemplate =
        "//li[@data-section-ref='%1$s']"
      + "/a[text()='Delete']";
    protected final TextBox courseEditInPlace =
        new TextBox(By.className("edit-in-place"), "Editor");
    
    private static final Label alert = new Label(
            By.xpath("//h2[text()='Alert']"), "Alert window");
    
    private String moduleDataRef;
    @SuppressWarnings("unused")
    private String index;

    /**
     * Entity creation is made through init method
     */
    private ModuleForm(final Label tempModule, String index) {
        super(tempModule.getLocator(), tempModule.getName());
        
        module = tempModule;
        this.index = index;
        moduleDataRef = module.getElement().getAttribute("data-module-ref");
        toggler = new Button(By.xpath(String.format(
                moduleTogglexPathTemplate, moduleDataRef)), index);
        moduleTitle = new Link(By.xpath(String.format(
                moduleTitlexPathTemplate, moduleDataRef)), index);
        moduleAssets = new ElementList(By.xpath(
                String.format(moduleAssetxPathTemplate, moduleDataRef)), "Assets",
                String.format(moduleAssetxPathTemplate, moduleDataRef)
              + "[contains(.,'%1$s')]");
        sectionTitles = new ElementList(By.xpath(String.format(
                sectionTitleList, moduleDataRef)), "Section Titles");
        sectionIDs = new ElementList(By.xpath(String.format(
                sectionIDList, moduleDataRef)), "Section Numbers");
        lock = new Label(By.xpath(String.format(
                lockSign, moduleDataRef)), index);
        handler = new Label(By.xpath(
                String.format(handlerXPathTemplate, moduleDataRef)), index);
        delete = new Button(By.xpath(
                String.format(deleteTemplate, moduleDataRef)), index);
        deleteConfirm = new Button(By.xpath(
                String.format(deleteConfirmTemplate, moduleDataRef)), index);
        duplicate = new Button(By.xpath(
                String.format(duplicateTemplate, moduleDataRef)), index);
    }

    public static ModuleForm init(String index) {
        String modifyIndex = index.replaceFirst("^0", "");
        Label tempModule = new Label(By.xpath(
                String.format(modulexPathTemplate, modifyIndex)), 
                String.format("Module %1$s", index));
    
        return new ModuleForm(tempModule, index);
    }

    public RemoteWebElement getModuleElement() {
        return moduleTitle.getElement();
    }
    
    public boolean isPresent(){
        return moduleTitle.isPresent(1);
    }
    
    public boolean isLocked() {
        return lock.isPresent();
    }

    public void expand() {
        if (sectionTitles.getListElements().size() == 0) {
            toggler.click();
        }
    }

    public void collapse() {
        if (sectionTitles.getListElements().size() != 0) {
            toggler.click();
        }
    }

    /**
     * Clicking on module's title
     */
    public void click() {
        moduleTitle.clickAndWait();
        //Check that Alert text is not displayed
        alert.assertIsAbsent();
    }
    
    public String getModuleTitle() {
        return moduleTitle.getText();
    }
    
    public ArrayList<String> getAssetNames() {
        ArrayList<String> result = new ArrayList<String>();
        for (WebElement el: moduleAssets.getListElements()) {
            result.add(el.getText());
        }
        return result;
    }
    
    public boolean hasAsset(String assetName) {
        return moduleAssets.hasListElement(assetName);
    }
    
    public void openAssetDetails(String assetName) {
        moduleAssets.selectListElement(assetName);
    }
    
    public String getAssetType(String assetName) {
        Label asset = new Label(By.xpath(
                "//li[contains(@class,'contain')]"
              + "[contains(.,'" + assetName + "')]"), "Asset");
        return asset.getElement().getAttribute("class").split(" ")[0];
    }
    
    public ArrayList<String> getSectionNames() {
        ArrayList<String> result = new ArrayList<String>();
        for (WebElement el: sectionTitles.getListElements()) {
            result.add(el.getText());
        }
        return result;
    }
    
    public ArrayList<String> getSectionIDs() {
        ArrayList<String> result = new ArrayList<String>();
        for (WebElement el: sectionIDs.getListElements()) {
            result.add(el.getText());
        }
        return result;
    }

    public List<WebElement> getSectionList() {
        expand();
        return sectionTitles.getListElements();
    }

    public List<WebElement> getSectionListNoExpand() {
        return sectionTitles.getListElements();
    }

    public void assertSectionPresent(String sectionName) {
        Assert.assertTrue(String.format(
            "Section '%1$s' hasn't been found", sectionName),
            sectionTitles.hasListElement(sectionName));
    }

    public void clickLastSection() {
        String sectionName = ((RemoteWebElement)
                getSectionList().get(getSectionList().size() - 1)).getText();
        Link sectionTitle = new Link(By.linkText(sectionName), sectionName);
        sectionTitle.clickAndWait();
    }

    public SectionForm openSection(String sectionName) {
        expand();
        Link sectionTitle = new Link(By.linkText(sectionName), sectionName);
        sectionTitle.clickAndWait();
        //Check that Alert text is not displayed
        alert.assertIsAbsent();
        return new SectionForm();
    }

    public SectionForm openSection(int sectionIndex) {
        String sectionXPath = String.format(
                sectionTitle, getSectionDataRef(sectionIndex), sectionIndex);
        Label section = new Label(By.xpath(sectionXPath), "Section");
        section.clickAndWait();
        return new SectionForm();
    }
    
    public String getSectionName(int sectionIndex) {
        return getSectionNames().get(sectionIndex);
    }
    
    public String getSectionDataRef(int sectionIndex) {
        String sectionXPath =
            String.format(sectionTemplate, moduleDataRef, sectionIndex);
        Label section = new Label(By.xpath(sectionXPath), "Section");
        return section.getElement().getAttribute("data-section-ref");
    }
    
    public boolean sectionCanBeRenamed(int sectionIndex) {
        openSection(sectionIndex); 
        return courseEditInPlace.isPresent(1);
    }

    public void renameSection(int sectionIndex, String newName){
        courseEditInPlace.setText(newName);
        courseEditInPlace.getElement().sendKeys(Keys.ENTER);
    }
    
    public boolean sectionCanBeDeleted(int sectionIndex) {
        String sectionDataRef = getSectionDataRef(sectionIndex);
        Button deleteSection = new Button(By.xpath(
                String.format(deleteSectionTemplate, sectionDataRef)),
                    "Delete");  
        return deleteSection.isPresent(1);
    }
    
    public void deleteSection(int sectionIndex){
        String sectionDataRef = getSectionDataRef(sectionIndex);
        Button deleteSection = new Button(By.xpath(
                String.format(deleteSectionTemplate, sectionDataRef)),
                    "Delete"); 
        deleteSection.clickAndWait();
        Button deleteSectionConfirm = new Button(By.xpath(
                String.format(deleteSectionConfirmTemplate, sectionDataRef)),
                    "Delete confirmation"); 
        deleteSectionConfirm.clickAndWait();
    }
    
    public boolean sectionCanBeDuplicated(int sectionIndex) {
        String sectionDataRef = getSectionDataRef(sectionIndex);
        Button duplicateSection = new Button(By.xpath(
                String.format(duplicateSectionTemplate, sectionDataRef)),
                    "Duplicate"); 
        return duplicateSection.isPresent(1);
    }
    
    
    public void duplicateSection(int sectionIndex){
        String sectionDataRef = getSectionDataRef(sectionIndex);
        Button duplicateSection = new Button(By.xpath(
                String.format(duplicateSectionTemplate, sectionDataRef)),
                    "Duplicate"); 
        duplicateSection.clickAndWait();
    }

    
    public SectionForm openRandomSection() {
        expand();
        sectionTitles.selectRandomElement();
        return new SectionForm();
    }

    public boolean isMovingAllowed() {
        if (handler.isPresent(1)) {
            return handler.getElement().getCssValue("cursor") != "auto";
        } else {
            return false;
        }
    }

    public void dragToElement(RemoteWebElement moduleDragTo) {
        Actions builder = new Actions(browser.getDriver());
        builder
            .moveToElement(handler.getElement())
            .moveToElement(moduleDragTo)
            .dragAndDrop(handler.getElement(), moduleDragTo)
            .build()
            .perform();
    }

    public void dragSection(int sectionFromIndex, int sectionToIndex) {
        WebElement sectionFrom =
            sectionIDs.getListElements().get(sectionFromIndex - 1);
        WebElement sectionTo   =
            sectionIDs.getListElements().get(sectionToIndex - 1); 
        Actions builder = new Actions(browser.getDriver());
        builder
            .moveToElement(sectionFrom)
            .moveToElement(sectionTo)
            .dragAndDrop(sectionFrom, sectionTo)
            .build()
            .perform();
    }

    public boolean canBeRenamed() {
        return courseEditInPlace.isPresent(1);
    }
    
    public void rename(String renamedModuleName) {
        courseEditInPlace.setText(renamedModuleName);
        courseEditInPlace.getElement().sendKeys(Keys.ENTER);
    }

    public void duplicate() {
        duplicate.clickAndWait();
    }

    public void delete() {
        delete.clickAndWait();
        deleteConfirm.clickAndWait();
    }

    public boolean canBeDuplicated() {
        return duplicate.isPresent(1);
    }

    public Object canBeDeleted() {
        return delete.isPresent(1);
    }

}
